<template>
  <el-upload
    :action="type === 'avatar' ? avatarUploadUrl : imageUploadUrl"
    :headers="uploadHeaders"
    :accept="accept"
    :before-upload="beforeUpload"
    :data="data"
    :show-file-list="false"
    :on-success="onSuccess"
    :on-error="onError"
    :on-progress="(event: any, file: any) => (progressFile = file)"
    :disabled="disabled"
    :drag="!src"
  >
    <div v-if="src" class="full-flex-center rounded-border relative hover:border-opacity-0">
      <img :src="src" class="max-w-full max-h-full block" />
      <div
        class="full-flex-center absolute rounded-md cursor-default bg-black bg-opacity-50 opacity-0 hover:opacity-100 space-x-4"
        @click.stop
      >
        <el-icon
          class="image-action"
          :title="$t('cms.cutImage')"
          @click="() => (cropperVisible = true)"
          ><Crop
        /></el-icon>
        <el-icon
          class="image-action"
          :title="$t('cms.previewImage')"
          @click="() => (previewVisible = true)"
          ><View
        /></el-icon>
        <el-icon
          class="image-action"
          :title="$t('cms.deleteImage')"
          @click="() => (src = undefined)"
          ><Delete
        /></el-icon>
      </div>
    </div>
    <el-progress
      v-else-if="progressFile.status === 'uploading'"
      type="circle"
      :percentage="parseInt(progressFile.percentage, 10)"
    />
    <div v-else class="el-upload--picture-card">
      <el-icon><Plus /></el-icon>
    </div>
  </el-upload>
  <div>
    <el-dialog v-model="previewVisible" top="5vh" :width="768" append-to-body destroy-on-close>
      <el-input v-model="src">
        <template #prepend>URL</template>
      </el-input>
      <img :src="src" alt="" class="mt-1 border border-gray-300" />
    </el-dialog>
  </div>
  <image-cropper
    v-model="cropperVisible"
    :type="type"
    :src="src"
    :width="width"
    :height="height"
    @success="onCropSuccess"
  />
</template>
<script setup lang="ts">
import { computed, ref, toRefs, PropType } from 'vue'
import { ElMessage, useFormItem } from 'element-plus'
import { Plus, Crop, View, Delete } from '@element-plus/icons-vue'
import { useI18n } from 'vue-i18n'
import { getAccessToken, getTenantId } from '@/utils/auth'
import { getSiteHeader } from '@/utils/cmscommon'
import { uploadSettings, imageUploadUrl, avatarUploadUrl } from '@/api/cms/upload/types'
import ImageCropper from './ImageCropper.vue'

// 'image/jpg,image/jpeg,image/png,image/gif'

const props = defineProps({
  modelValue: { type: String, default: null },
  fileAccept: { type: String, default: null },
  fileMaxSize: { type: Number, default: null },
  width: { type: Number, default: null },
  height: { type: Number, default: null },
  /**
   * none: 原图上传, cut: 自动裁剪, resize: 自动压缩, manual: 手动裁剪
   */
  mode: { type: String as PropType<'none' | 'cut' | 'resize' | 'manual'>, default: 'none' },
  /**
   * image: 图片上传, avatar: 头像上传
   */
  type: { type: String as PropType<'image' | 'avatar'>, default: 'image' },
  disabled: { type: Boolean, default: false }
})

const emit = defineEmits({ 'update:modelValue': null, cropSuccess: null })

const { modelValue, type, width, height, mode, fileAccept, fileMaxSize } = toRefs(props)
const { t } = useI18n()
const progressFile = ref<any>({})
const previewVisible = ref<boolean>(false)
const cropperVisible = ref<boolean>(false)
const { formItem } = useFormItem()
const uploadHeaders = ref()
const src = computed({
  get: (): string | undefined => modelValue.value,
  set: (val?: string) => {
    emit('update:modelValue', val)
    formItem?.validate?.('change').catch((err: any) => {
      if (import.meta.env.MODE !== 'production') {
        console.warn(err)
      }
    })
  }
})
const resizable = computed(() => ['cut', 'resize'].includes(mode.value))
const data = computed(() => {
  const params: any = { resizeMode: mode.value === 'cut' ? 'cut' : 'normal' }
  if (width.value != null) {
    // 为0不限制，为空则依然受全局图片宽高限制
    params.maxWidth = resizable.value ? width.value : 0
  }
  if (height.value != null) {
    // 为0不限制，为空则依然受全局图片宽高限制
    params.maxHeight = resizable.value ? height.value : 0
  }
  return params
})
const accept = computed(() => fileAccept.value ?? uploadSettings.imageInputAccept)
const maxSize = computed(() => fileMaxSize.value ?? uploadSettings.imageLimitByte)
const beforeUpload = (file: any) => {
  if (maxSize.value > 0 && file.size > maxSize.value) {
    ElMessage.error(t('cms.error.fileMaxSize', { size: `${maxSize.value / 1024 / 1024} MB` }))
    return false
  }
  uploadHeaders.value = {
    Authorization: 'Bearer ' + getAccessToken(),
    'tenant-id': getTenantId(),
    zrcms_site_id: getSiteHeader()
  }
  return true
}
const onError = (error: Error) => {
  ElMessage.error(t('上传失败，请您重新上传！'))
  console.log(error)
}
const onSuccess = (res: any) => {
  if (res.code == 0) {
    ;(src.value = res.data.url), (cropperVisible.value = mode.value === 'manual')
  } else {
    ElMessage.error(t('上传失败，请您重新上传！错误原因 ', res.msg))
    console.log(res.msg)
  }
}
const onCropSuccess = (url: string) => {
  src.value = url
  emit('cropSuccess', url)
}
</script>
<style lang="scss" scoped>
:deep(.el-dialog__headerbtn) {
  top: 4px;
}

:deep(.el-upload) {
  width: 148px;
  height: 148px;
}

.full-flex-center {
  @apply w-full h-full flex justify-center items-center;
}

.rounded-border {
  @apply rounded-md bg-gray-50;

  border: 1px solid #c0ccda;
}

.image-action {
  @apply cursor-pointer text-xl text-white;
}

:deep(.el-upload-dragger) {
  padding: 0;
}

:deep(.el-upload--picture-card) {
  border: 0;
}
</style>
